/***********************************************************************************************
    GPIO unit for R408 SoC
    Register define(from address offest0):
    +0 P_in    : input from GPIO
    +1 P_out   : data out to GPIO
    +2 P_mode0 : Port mode0, this register is for direction control, 0=input 1=output, reset=00000000(all input)
    +3 P_mode1 : Poet mode1, this register is for the 7-segment decoder control, bit0 control the 7-segment decoder
                  set bit0 = 1 to open the decoder. reset = 00000000

                    You can add anything you like to this unit!
************************************************************************************************/
module gpio(
//-------------GPIO port------------
    input wire [7:0]P_in,
    output wire [7:0]D_out,
    output reg [7:0]P_mode0,
//------------Global signals--------
    input wire clk,
    input wire rstn,
//-----------Wishbone BUS-----------
    input wire [9:0]WB_ADRi,
    output reg [7:0]WB_DATo,
    input wire [7:0]WB_DATi,
    input wire WB_WEi,
    input wire WB_CYCi,
    input wire WB_STBi,
    output wire WB_ACKo

);
//------------------register select-----------------
//wire Pin_select;			//P_in register is not use for write
wire Pout_select;
wire Pmode1_select;
wire Pmode0_select;

wire [7:0]Sdec_out;         //7-segment decoder output
//-----------Regs defines-----------
reg [7:0] Pin;
reg [7:0] P_out;
//reg [7:0] P_mode0;      //direction, 1=out 0=in
reg [7:0] P_mode1;      //GPIO mode, bit0: 7-seg decode enable
//-----------------P port output-------------------
assign D_out = P_mode1[0] ? Sdec_out : P_out;
/*
assign P[0] = P_mode0[0] ? D_out[0] : 1'bz;
assign P[1] = P_mode0[1] ? D_out[1] : 1'bz;
assign P[2] = P_mode0[2] ? D_out[2] : 1'bz;
assign P[3] = P_mode0[3] ? D_out[3] : 1'bz;
assign P[4] = P_mode0[4] ? D_out[4] : 1'bz;
assign P[5] = P_mode0[5] ? D_out[5] : 1'bz;
assign P[6] = P_mode0[6] ? D_out[6] : 1'bz;
assign P[7] = P_mode0[7] ? D_out[7] : 1'bz;
*/
//-----------------regs select------------------
//assign Pin_select    = WB_CYCi & WB_STBi & (WB_ADRi == 10'h0);
assign Pout_select   = WB_CYCi & WB_STBi & (WB_ADRi == 10'h1);
assign Pmode0_select = WB_CYCi & WB_STBi & (WB_ADRi == 10'h2);
assign Pmode1_select = WB_CYCi & WB_STBi & (WB_ADRi == 10'h3);

//-----------------regs--------------------
always@(posedge clk)begin
    Pin <= P_in;    
end
//---------------Pmode0------------------
always@(posedge clk)begin
    if(!rstn)begin
        P_mode0 <= 8'h00;
    end
    else if(Pmode0_select & WB_WEi)begin
        P_mode0 <= WB_DATi;
    end
end
//----------------Pmode1-----------------
always@(posedge clk)begin
    if(!rstn)begin
        P_mode1 <= 8'h00;
    end
    else if(Pmode1_select & WB_WEi)begin
        P_mode1 <= WB_DATi;
    end
end
always@(posedge clk)begin
    if(!rstn)begin
        P_out <= 8'h00;
    end
    else if(Pout_select & WB_WEi)begin
        P_out <= WB_DATi;
    end
end
//---------------wishbone signals------------
//-----------DATA-----------
always@(*)begin
    case(WB_ADRi[1:0])
        2'h0    :   WB_DATo <= Pin;
        2'h1    :   WB_DATo <= P_out;
        2'h2    :   WB_DATo <= P_mode0;
        2'h3    :   WB_DATo <= P_mode1;
        default :   WB_DATo <= 8'h00;
    endcase
end
//----------ACK----------------
assign WB_ACKo = 1'b1;

seg7            seg7(

.test               (1'b0),
.blank              (1'b0),
.in                 (P_out[3:0]),
.hex                (Sdec_out)	//lowactive g f e d c b a 
);



endmodule
//hex-7-segment decoder

module seg7(

input wire test,
input wire blank,
input wire [3:0]in,
output reg [6:0]hex	//lowactive g f e d c b a 
);

always@(*)begin
	if(blank)begin
		hex <= 7'b111_1111;	//blank
	end
	else begin
	case({test,in})
		5'b00000 	:	hex <= 7'b100_0000;
		5'b00001	:	hex <= 7'b111_1001;
		5'b00010	:	hex <= 7'b010_0100;
		5'b00011	:	hex <= 7'b011_0000;
		5'b00100	:   hex <= 7'b001_1001;
		5'b00101	:	hex <= 7'b001_0010;
		5'b00110	:   hex <= 7'b000_0010;
		5'b00111	:	hex <= 7'b111_1000;
		5'b01000	:	hex <= 7'b000_0000;
		5'b01001	:   hex <= 7'b001_0000;
		5'b01010	:   hex <= 7'b000_1000;
		5'b01011	:	hex <= 7'b000_0011;
		5'b01100	:	hex <= 7'b100_0110;
		5'b01101	:	hex <= 7'b010_0001; 
		5'b01110	:	hex <= 7'b000_0110;
		5'b01111	:   hex <= 7'b000_1110;
	default : hex <= 7'b000_0000;
	endcase
	end
end

endmodule